package com.niiwoo.civet.trade.service.local.kaola;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.google.common.base.Preconditions;
import com.lycheepay.gateway.client.GBPService;
import com.lycheepay.gateway.client.GatewayClientException;
import com.lycheepay.gateway.client.KftService;
import com.lycheepay.gateway.client.dto.CollectFromBankAccountDTO;
import com.lycheepay.gateway.client.dto.QueryTradeRecordDTO;
import com.lycheepay.gateway.client.dto.QueryTradeRecordResultDTO;
import com.lycheepay.gateway.client.dto.TradeResultDTO;
import com.lycheepay.gateway.client.dto.gbp.TreatyRecordDTO;
import com.lycheepay.gateway.client.dto.gbp.TreatyRecordQueryDTO;
import com.lycheepay.gateway.client.dto.gbp.TreatyRecordQueryResponseDTO;
import com.lycheepay.gateway.client.dto.gbp.TreatyRecordResponseDTO;
import com.lycheepay.gateway.client.security.KeystoreSignProvider;
import com.lycheepay.gateway.client.security.SignProvider;
import com.niiwoo.civet.trade.constant.DatePatternConstant;
import com.niiwoo.civet.trade.dao.entity.KaolaWithholdOrder;
import com.niiwoo.civet.trade.property.LycheePayProperties;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.FastDateFormat;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 快付通支付服务
 *
 * @author lichuanzhi
 * @date 2018/04/17
 */

@Slf4j
@Service
@EnableConfigurationProperties(LycheePayProperties.class)
public class LycheePayRequestService {

    private  KftService service;
    private  GBPService gbpService;

    @Autowired
    private LycheePayProperties lycheePayProperties;
    @Autowired
    private PrivacyMasks privacyMasks;

    @PostConstruct
    private void init(){
        // 初始化证书 证书类型、证书路径、证书密码、别名、证书容器密码
        try {
            ClassPathResource classPathResource = new ClassPathResource(lycheePayProperties.getKeyStore().getFileSystemPath());
            SignProvider keystoreSignProvider = new KeystoreSignProvider("PKCS12",
                    classPathResource.getFile().getAbsolutePath(), lycheePayProperties.getKeyStore().getPassword().toCharArray(), null,
                    lycheePayProperties.getKeyStore().getPassword().toCharArray());

            // 签名提供者、商户服务器IP(callerIp)、下载文件路径(暂时没用)
            service = new KftService(keystoreSignProvider, lycheePayProperties.getCallerIp(), "zh_CN", null);
            service.setHttpPort(lycheePayProperties.getPort());
            service.setConnectionTimeoutSeconds(60);
            service.setResponseTimeoutSeconds(10 * 60);
            gbpService = new GBPService(keystoreSignProvider, lycheePayProperties.getCallerIp(), "zh_CN", null);
            gbpService.setHttpPort(lycheePayProperties.getPort());
            gbpService.setConnectionTimeoutSeconds(60);
            gbpService.setResponseTimeoutSeconds(10 * 60);
        } catch (Exception e) {
            log.error("快付通##初始化异常",e);
        }
    }

    /**
     * 单笔代收接口
     * @param withholdOrder 代扣订单
     * @return 交易结果
     * @throws GatewayClientException
     */
    public TradeResultDTO collectFromBankAccount(KaolaWithholdOrder withholdOrder, Long projectId) throws GatewayClientException {
        CollectFromBankAccountDTO dto = new CollectFromBankAccountDTO();
        dto.setService("gbp_collect");
        dto.setVersion(lycheePayProperties.getVersion());
        dto.setMerchantId(lycheePayProperties.getMerchantId());
        dto.setProductNo(lycheePayProperties.getProductNo().getGbpCollect());
        dto.setCurrency("CNY");
        dto.setOrderNo(withholdOrder.getOrderNo());
        dto.setReqNo(withholdOrder.getReqNo());
        dto.setTradeName(withholdOrder.getRemark());

        //交易时间,注意此时间取值一般为商户方系统时间而非快付通生成此时间
        dto.setTradeTime(withholdOrder.getTradeTime());
        //dto.setMerchantBankAccountNo("商户对公账号");//商户用于收款的银行账户,资金不落地模式时必填（重要参数）
        //交易金额，单位：分，不支持小数点
        dto.setAmount(withholdOrder.getAmount().multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_EVEN).toString());
        dto.setCustBankNo(withholdOrder.getCustBankNo());
        dto.setCustBankAccountNo(privacyMasks.decryptPrivacy(withholdOrder.getCustBankAccountNo()));
        dto.setCustBindPhoneNo(privacyMasks.decryptPrivacy(withholdOrder.getCustBindPhoneNo()));
        dto.setCustName(withholdOrder.getCustName());
        dto.setCustBankAcctType("1");
        dto.setCustAccountCreditOrDebit("1");
        dto.setCustCertificationType("0");
        dto.setCustID(privacyMasks.decryptPrivacy(withholdOrder.getCustId()));
        dto.setCustProtocolNo(withholdOrder.getCustProtocolNo());
        log.info("标的{}，单笔收款接口##请求参数:{}", projectId, JSON.toJSONString(dto, (PropertyFilter) (object, name, value) -> !"allParameters".equals(name)));
        TradeResultDTO result = service.collectFromBankAccount(dto);
        log.info("标的{}，单笔收款接口##响应:{}", projectId, JSON.toJSONString(result));
        return result;
    }

    /**
     * 交易结果查询接口
     * @param criterias 查询条件
     * @return 交易结果
     * @throws GatewayClientException
     */
    public QueryTradeRecordResultDTO queryTradeRecord(List<QueryTradeRecordDTO.Criteria> criterias) throws GatewayClientException {
        Preconditions.checkArgument(!CollectionUtils.isEmpty(criterias),"查询条件不可为空");
        QueryTradeRecordDTO dto = new QueryTradeRecordDTO();
        dto.setService("trade_record_query");
        dto.setVersion(lycheePayProperties.getVersion());
        dto.setMerchantId(lycheePayProperties.getMerchantId());
        dto.setProductNo(lycheePayProperties.getProductNo().getTradeRecordQuery());

        //.addCriteria(dto.new Criteria("原交易的产品编号", "", "原交易订单号"));// 第二个参数为空， 一次可查询多个订单,最多200条
        criterias.forEach(dto::addCriteria);
        log.info("结果查询##请求参数:{}", JSON.toJSONString(dto, (PropertyFilter) (object, name, value) -> !"allParameters".equals(name)));
        QueryTradeRecordResultDTO result = service.queryTradeRecord(dto);
        log.info("结果查询##请求参数:{}", JSON.toJSONString(dto));
        return result;
    }

    /**
     * 协议申请上送接口
     * @param withholdOrder 代扣订单
     * @param merchantTreatyNo 代扣协议编号
     * @return 上送结果
     * @throws GatewayClientException
     */
    public TreatyRecordResponseDTO sendTreatyRecord2KFT(KaolaWithholdOrder withholdOrder, String merchantTreatyNo) throws GatewayClientException {
        TreatyRecordDTO dto = new TreatyRecordDTO();
        dto.setService("gbp_send_treaty_record_to_kft");
        dto.setVersion(lycheePayProperties.getVersion());
        dto.setMerchantId(lycheePayProperties.getMerchantId());

        // 订单号同一个商户必须保证唯一
        dto.setOrderNo(withholdOrder.getOrderNo());

        // 商户与用户的协议号,就是代扣合同编号
        dto.setMerchantTreatyNo(merchantTreatyNo);
        dto.setTreatyType("1");
        dto.setStartDate(FastDateFormat.getInstance(DatePatternConstant.YYYYMMDD).format(new Date()));
        dto.setEndDate(FastDateFormat.getInstance(DatePatternConstant.YYYYMMDD).format(new DateTime().plusYears(1).toDate()));
        dto.setHolderName(withholdOrder.getCustName());

        // 银行卡行别，测试环境只支持建行卡
        dto.setBankType(withholdOrder.getCustBankNo());
        dto.setBankCardType("1");
        dto.setBankCardNo(privacyMasks.decryptPrivacy(withholdOrder.getCustBankAccountNo()));
        dto.setMobileNo(privacyMasks.decryptPrivacy(withholdOrder.getCustBindPhoneNo()));
        dto.setCertificateType("0");
        dto.setCertificateNo(privacyMasks.decryptPrivacy(withholdOrder.getCustId()));
        dto.setCurrencyType("CNY");

        // 费项代码,具体看文档,生产环境由运营提供
        dto.setPaymentItem("04903");
        dto.setNote("代扣协议");
        log.info("协议申请##请求信息为:" + JSON.toJSONString(dto, (PropertyFilter) (object, name, value) -> !"allParameters".equals(name)));
        TreatyRecordResponseDTO result = gbpService.sendTreatyRecord2KFT(dto);
        log.info("协议申请##响应信息为:" + JSON.toJSONString(result));
        return result;
    }

    /**
     * 协议状态查询接口
     * @param recordResponseDTO 上送结果
     * @return 协议状态
     * @throws GatewayClientException
     */
    public TreatyRecordQueryResponseDTO queryTreatyRecordInfo(TreatyRecordResponseDTO recordResponseDTO) throws GatewayClientException {
        TreatyRecordQueryDTO dto = new TreatyRecordQueryDTO();
        dto.setService("gbp_query_treaty_record_info");
        dto.setVersion(lycheePayProperties.getVersion());
        dto.setMerchantId(lycheePayProperties.getMerchantId());

        // 订单号对应协议上送接口的订单号
        dto.setOrderNo(recordResponseDTO.getOrderNo());

        // 协议上送接口返回的协议号
        dto.setTreatyNo(recordResponseDTO.getTreatyNo());
        log.info("协议查询##请求信息为:" + JSON.toJSONString(dto, (PropertyFilter) (object, name, value) -> !"allParameters".equals(name)));
        TreatyRecordQueryResponseDTO result = gbpService.queryTreatyRecordInfo(dto);
        log.info("协议查询##响应信息为:" + JSON.toJSONString(result));
        return result;
    }

}
